/*
* Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* $Id: sessionmodel.cpp 528 2009-05-14 16:07:34Z jpnurmi $
*/

#include "sessionmodel.h"
#include "sessionmodelitem.h"
#include <ircutil.h>
#include <QtDebug>

SessionModel::SessionModel(QObject* parent)
    : QStandardItemModel(0, 1, parent) // 0 rows, 1 col
{
}

void SessionModel::nickChanged(const QString& origin, const QString& nick)
{
    QString source = Irc::Util::nickFromTarget(origin);

    if (d.topLevelItems.contains(source.toLower()))
    {
        SessionModelItem* receiver = topLevelItem(source);
        receiver->setData(nick, SessionModelItem::NameRole);
    }

    for (int i = 0; i < rowCount(); ++i)
    {
        SessionModelItem* receiver = static_cast<SessionModelItem*>(item(i));
        SessionModelItem* participant = receiver->findChild(source);
        if (participant)
        {
            participant->setData(nick, SessionModelItem::NameRole);
            receiver->sortChildren(0);
        }
    }
}

void SessionModel::quit(const QString& origin)
{
    QString source = Irc::Util::nickFromTarget(origin);
    foreach (SessionModelItem* receiver, d.topLevelItems)
    {
        SessionModelItem* participant = receiver->findChild(source);
        if (participant)
            receiver->removeRow(participant->row());
    }
}

void SessionModel::joined(const QString& origin, const QString& channel)
{
    QString source = Irc::Util::nickFromTarget(origin);
    SessionModelItem* receiver = topLevelItem(channel);
    receiver->childItem(source);
    receiver->sortChildren(0);
}

void SessionModel::parted(const QString& origin, const QString& channel, bool me)
{
    QString source = Irc::Util::nickFromTarget(origin);
    for (int i = rowCount() - 1; i >= 0; --i)
    {
        SessionModelItem* receiver = static_cast<SessionModelItem*>(item(i));
        SessionModelItem* participant = receiver->findChild(source);
        // nick in a channel
        if (participant && !receiver->text().compare(channel, Qt::CaseInsensitive))
            receiver->removeRow(participant->row());

        // the channel itself
        if (me && !receiver->text().compare(channel, Qt::CaseInsensitive))
            removeTopLevelItem(receiver->row());
   }
}

void SessionModel::modeChanged(const QString& receiver, const QString& mode, const QString& args)
{
    SessionModelItem* receiverItem = topLevelItem(receiver);
    if (receiverItem)
    {
        SessionModelItem* participant = receiverItem->findChild(args);
        if (participant)
            participant->setMode(mode);
    }
}

void SessionModel::kicked(const QString& channel, const QString& nick)
{
    SessionModelItem* receiver = topLevelItem(channel);
    SessionModelItem* participant = receiver->findChild(nick);
    if (participant)
        receiver->removeRow(participant->row());
}

void SessionModel::numericMessageReceived(uint event, const QStringList& params)
{
    switch (event)
    {
        case Irc::Rfc::RPL_NAMREPLY:
        {
            QStringList list = params;
            list.removeAll("=");
            list.removeAll("@");

            SessionModelItem* item = topLevelItem(list.value(1));
            QStringList nicks = list.value(2).split(" ", QString::SkipEmptyParts);
            foreach (const QString& nick, nicks) {
                SessionModelItem* child = item->childItem(nick);
                child->setData(nick); // assure @/+
            }
            item->sortChildren(0);
        }
        break;

        default:
            break;
    }
}

SessionModelItem* SessionModel::topLevelItem(const QString& name)
{
    QString lower = name.toLower();
    if (!d.topLevelItems.contains(lower))
    {
        SessionModelItem* item = new SessionModelItem();
        item->setData(name);
        d.topLevelItems.insert(lower, item);
        appendRow(item);
    }
    return d.topLevelItems.value(lower);
}

void SessionModel::removeTopLevelItem(int row)
{
    QList<QStandardItem*> items = invisibleRootItem()->takeRow(row);
    foreach (QStandardItem* item, items)
        d.topLevelItems.remove(d.topLevelItems.key(static_cast<SessionModelItem*>(item))); 
    qDeleteAll(items);
}
